package com.spzx.product.service.impl;

import com.alibaba.fastjson.JSON;
import com.spzx.common.core.constant.ProductConstants;
import com.spzx.common.core.exception.ServiceException;
import com.spzx.common.core.utils.StringUtils;
import com.spzx.common.redis.service.RedisService;
import com.spzx.product.domain.Product;
import com.spzx.product.domain.ProductDetails;
import com.spzx.product.domain.ProductSku;
import com.spzx.product.domain.SkuStock;
import com.spzx.product.enums.ProductAuditStatus;
import com.spzx.product.mapper.ProductDetailsMapper;
import com.spzx.product.mapper.ProductMapper;
import com.spzx.product.mapper.ProductSkuMapper;
import com.spzx.product.mapper.SkuStockMapper;
import com.spzx.product.service.ProductService;
import com.spzx.product.vo.ProductVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Service
public class ProductServiceImpl implements ProductService {

    @Autowired
    private ProductMapper productMapper;

    @Autowired
    private ProductDetailsMapper productDetailsMapper;

    @Autowired
    private ProductSkuMapper productSkuMapper;

    @Autowired
    private SkuStockMapper skuStockMapper;

    @Autowired
    private ThreadPoolExecutor threadPool;

    @Autowired
    private RedisService redisService;

    @Override
    public List<ProductVo> pageList(Product product) {
        List<ProductVo> list = productMapper.selectList(product);
        return list;
    }

    @Override
    @Transactional
    public void save(ProductVo productVo) {
        // 保存商品信息 product
        Product product = new Product();
        BeanUtils.copyProperties(productVo, product);
        productMapper.save(product);
        // 保存详情图片列表 product_details
        ProductDetails details = new ProductDetails();
        details.setProductId(product.getId());
        details.setImageUrls(String.join(",", productVo.getDetailsImageUrlList()));
        BeanUtils.copyProperties(productVo, details);
        productDetailsMapper.insert(details);
        // 保存商品sku信息 product_sku
        List<ProductSku> productSkuList = productVo.getProductSkuList();
        int i = 0;
        for (ProductSku item : productSkuList) {
            item.setSkuCode(product.getId() + "_" + i);
            item.setProductId(product.getId());
            item.setSkuName(product.getName() + " " + item.getSkuSpec());
            i++;
        }
        productSkuMapper.saveBatch(productSkuList);
        // 保存商品库存信息 sku_stock
        List<SkuStock> skuStockList = productSkuList.stream().map(item -> {
            SkuStock skuStock = new SkuStock();
            skuStock.setSkuId(item.getId());
            skuStock.setTotalNum(item.getStockNum());
            skuStock.setLockNum(0);
            skuStock.setAvailableNum(item.getStockNum());
            skuStock.setSaleNum(0);
            BeanUtils.copyProperties(productVo, skuStock);
            return skuStock;
        }).collect(Collectors.toList());
        skuStockMapper.saveBatch(skuStockList);
    }

    @Override
    public ProductVo getInfo(Long id) {
        // 先尝试从redis缓存中获取商品详情，若未获取到内容，再查询数据库
        String cacheObject = redisService.getCacheObject(ProductConstants.PRODUCT_INFO_KEY + id);
        if (StringUtils.isNotEmpty(cacheObject)) {
            ProductVo vo = JSON.parseObject(cacheObject, ProductVo.class);
            return vo;
        } else {
            ProductVo vo = new ProductVo();
            CompletableFuture<Void> productFuture = CompletableFuture.runAsync(() -> {
                Product product = productMapper.getById(id);
                if (ObjectUtils.isEmpty(product)) {
                    throw new ServiceException("该商品不存在");
                }
                BeanUtils.copyProperties(product, vo);
            }, threadPool);
            CompletableFuture<Void> detailsFuture = CompletableFuture.runAsync(() -> {
                ProductDetails details = productDetailsMapper.selectDetails(id);
                if (details != null) {
                    List<String> detailsImageUrlList = Arrays.asList(details.getImageUrls().split(","));
                    vo.setDetailsImageUrlList(detailsImageUrlList);
                }
            }, threadPool);
            CompletableFuture<Void> skusFuture = CompletableFuture.runAsync(() -> {
                List<ProductSku> skus = productSkuMapper.selectSkus(id);
                vo.setProductSkuList(skus);
            }, threadPool);
            CompletableFuture.allOf(productFuture, detailsFuture, skusFuture).join();
            redisService.setCacheObject(ProductConstants.PRODUCT_INFO_KEY + id,
                    JSON.toJSONString(vo),
                    ProductConstants.PRODUCT_INFO_TTL,
                    TimeUnit.MINUTES);
            return vo;
        }
    }

    @Override
    @Transactional
    public void update(ProductVo productVo) {
        // 修改商品信息
        CompletableFuture.runAsync(() -> {
            Product product = new Product();
            BeanUtils.copyProperties(productVo, product);
            productMapper.update(product);
        }, threadPool).exceptionally(ex -> {
            throw new ServiceException("该商品已经存在");
        }).join();
        // 修改商品图片列表
        CompletableFuture.runAsync(() -> {
            ProductDetails details = new ProductDetails();
            details.setProductId(productVo.getId());
            details.setImageUrls(String.join(",", productVo.getDetailsImageUrlList()));
            productDetailsMapper.update(details);
        }, threadPool);
        // 修改商品sku信息
        CompletableFuture.runAsync(() -> {
            List<ProductSku> productSkuList = productVo.getProductSkuList();
            for (ProductSku item : productSkuList) {
                item.setSkuName(productVo.getName() + " " + item.getSkuSpec());
            }
            productSkuMapper.updateBatch(productSkuList);
        }, threadPool);
        // 修改库存信息
        CompletableFuture.runAsync(() -> {
            List<SkuStock> skuStockList = productVo.getProductSkuList().stream().map(item -> {
                SkuStock skuStock = new SkuStock();
                skuStock.setSkuId(item.getId());
                skuStock.setTotalNum(item.getStockNum());
                return skuStock;
            }).collect(Collectors.toList());
            skuStockMapper.updateBatch(skuStockList);
        }, threadPool);
        // 删除缓存信息
        redisService.deleteObject(ProductConstants.PRODUCT_INFO_KEY + productVo.getId());
    }

    @Override
    @Transactional
    public void delete(Long[] ids) {
        productMapper.delete(ids);
        productDetailsMapper.delete(ids);
        List<Long> skuIds = productSkuMapper.selectIds(ids);
        productSkuMapper.delete(skuIds);
        skuStockMapper.delete(skuIds);
        // 删除缓存信息
        List<String> keys = new ArrayList<>();
        for (Long id : ids) {
            keys.add(ProductConstants.PRODUCT_INFO_KEY + id);
        }
        redisService.deleteObject(keys);
    }

    @Override
    public void updateAuditStatus(Long id, Integer auditStatus) {
        Product product = new Product();
        product.setId(id);
        product.setAuditStatus(auditStatus);
        product.setAuditMessage(auditStatus == ProductAuditStatus.PASS.getCode() ?
                ProductAuditStatus.PASS.getInfo() : ProductAuditStatus.UNPASS.getInfo());
        productMapper.update(product);
    }

    @Override
    public void updateStatus(Long id, Integer status) {
        Product product = new Product();
        product.setId(id);
        product.setStatus(status);
        productMapper.update(product);
    }
}
